package com.ruoyi.cm.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.json.JSON;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.therapi.runtimejavadoc.repack.com.eclipsesource.json.Json;
import com.ruoyi.common.excel.CustomCellWriteWidthConfig;
import com.ruoyi.common.excel.ExcelMergeHandler;
import com.ruoyi.common.excel.ExcelMergeHandlerTotal;
import com.ruoyi.common.excel.ExcelStyleHandler;
import com.ruoyi.common.utils.JsonUtils;
import lombok.RequiredArgsConstructor;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckLogin;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.core.validate.EditGroup;
import com.ruoyi.common.core.validate.QueryGroup;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.cm.domain.vo.CmBaContractSheetsVo;
import com.ruoyi.cm.domain.bo.CmBaContractSheetsBo;
import com.ruoyi.cm.service.ICmBaContractSheetsService;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 合同清单详情
 *
 * @author zyb
 * @date 2024-09-24
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cm/baContractSheets")
public class CmBaContractSheetsController extends BaseController {

    private final ICmBaContractSheetsService iCmBaContractSheetsService;

    /**
     * 查询合同清单详情列表
     */
    @SaCheckLogin
    @GetMapping("/list")
    public TableDataInfo<CmBaContractSheetsVo> list(CmBaContractSheetsBo bo, PageQuery pageQuery) {
        return iCmBaContractSheetsService.queryPageList(bo, pageQuery);
    }

    /**
     * 查询合同清单详情列表
     */
    @SaCheckLogin
    @GetMapping("/listData")
    public Map<String,Object> listData(CmBaContractSheetsBo bo) {
        return iCmBaContractSheetsService.queryList(bo);
    }

    /**
     * 导出合同清单详情列表
     */
    @SaCheckLogin
    @Log(title = "合同清单详情", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(CmBaContractSheetsBo bo, HttpServletResponse response) {
        Map<String, Object> map = iCmBaContractSheetsService.queryList(bo);
        Object cmBaContractSheetsVos = map.get("cmBaContractSheetsVos");
        List<CmBaContractSheetsVo> list = (List<CmBaContractSheetsVo>)cmBaContractSheetsVos;
        ExcelUtil.exportExcel(list, "合同清单详情", CmBaContractSheetsVo.class, response);
    }

    /**
     * 获取合同清单详情详细信息
     *
     * @param sheetId 主键
     */
    @SaCheckLogin
    @GetMapping("/{sheetId}")
    public R<CmBaContractSheetsVo> getInfo(@NotNull(message = "主键不能为空")
                                     @PathVariable Long sheetId) {
        return R.ok(iCmBaContractSheetsService.queryById(sheetId));
    }

    /**
     * 新增合同清单详情
     */
    @SaCheckLogin
    @Log(title = "合同清单详情", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody CmBaContractSheetsBo bo) {
        return toAjax(iCmBaContractSheetsService.insertByBo(bo));
    }

    /**
     * 新增合同清单详情
     */
    @SaCheckLogin
    @Log(title = "合同清单详情", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping("/addBatch")
    public R<Void> addBatch(@Validated(AddGroup.class) @RequestBody List<CmBaContractSheetsBo> boList) {
        return toAjax(iCmBaContractSheetsService.insertBatchByBo(boList));
    }

    /**
     * 修改合同清单详情
     */
    @SaCheckLogin
    @Log(title = "合同清单详情", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody CmBaContractSheetsBo bo) {
        return toAjax(iCmBaContractSheetsService.updateByBo(bo));
    }

    /**
     * 修改合同清单批量
     */
    @SaCheckLogin
    @Log(title = "合同清单详情", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("/editBatch")
    public R<Void> editBatch(@Validated(EditGroup.class) @RequestBody List<CmBaContractSheetsBo> boList) {
        return toAjax(iCmBaContractSheetsService.editBatch(boList));
    }

    /**
     * 合同清单批量变更信息保存
     */
    @SaCheckLogin
    @Log(title = "合同清单详情", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping("/editChgBatch")
    public R<Void> editChgBatch(@Validated(EditGroup.class) @RequestBody List<CmBaContractSheetsBo> boList) {
        return toAjax(iCmBaContractSheetsService.editChgBatch(boList));
    }

    /**
     * 删除合同清单详情
     *
     * @param sheetIds 主键串
     */
    @SaCheckLogin
    @Log(title = "合同清单详情", businessType = BusinessType.DELETE)
    @DeleteMapping("/{sheetIds}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] sheetIds) {
        return toAjax(iCmBaContractSheetsService.deleteWithValidByIds(Arrays.asList(sheetIds), true));
    }


    /**
     * 查询开票详情
     */
    @SaCheckLogin
    @GetMapping("/listBillingInfo")
    public R<Map<String,Object>> listBillingInfo(String bdId,String zdId) {
        return R.ok(iCmBaContractSheetsService.listBillingInfo(bdId,zdId));
    }


    /**
     * 导出合同清单详情列表
     */
    @SaCheckLogin
    @PostMapping("/listBillingInfoExport")
    public void listBillingInfoExport(CmBaContractSheetsBo bo, HttpServletResponse response) {
        String bdId =ObjectUtils.isNotEmpty(bo.getBdId())? String.valueOf(bo.getBdId()):null;
        String zdId =ObjectUtils.isNotEmpty(bo.getZdId())? String.valueOf(bo.getZdId()):null;
        Map<String, Object> map = iCmBaContractSheetsService.listBillingInfoExport(bdId,zdId);
        if (CollectionUtils.isNotEmpty(map)){
            List<List<String>> heads = (List<List<String>>) map.get("heads");
            List<Map<String, Object>> list  = (List<Map<String, Object>>) map.get("result");
            List<Map<String, Object>> resultHeaderList  = (List<Map<String, Object>>) map.get("resultHeader");
            Map<String, Object> mapTotal  = (Map<String, Object>) map.get("total");
            List<List<String>> total = new ArrayList<>();
            //获取数据
            if (CollectionUtils.isNotEmpty(list)){
                for (Map<String, Object> map1 : list) {
                    List<String> info = new ArrayList<>();
                    info.add(ObjectUtils.isNotEmpty(map1.get("vuhao"))?String.valueOf(map1.get("vuhao")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("sheetTypeName"))?String.valueOf(map1.get("sheetTypeName")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("sheetFeaturesName"))?String.valueOf(map1.get("sheetFeaturesName")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("sheetUnit"))?String.valueOf(map1.get("sheetUnit")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("initRongliang"))?String.valueOf(map1.get("initRongliang")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("initDanjia"))?String.valueOf(map1.get("initDanjia")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("initZongjia"))?String.valueOf(map1.get("initZongjia")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("initZongjiaSum"))?String.valueOf(map1.get("initZongjiaSum")):null);
                    info.add(ObjectUtils.isNotEmpty(map1.get("sheetTaxRate"))?String.valueOf(map1.get("sheetTaxRate")):null);

                    BigDecimal ljkpje = BigDecimal.ZERO;
                    for (int i=0;i<resultHeaderList.size();i++){
                        Map<String, Object> map2 = resultHeaderList.get(i);
                        info.add(ObjectUtils.isNotEmpty(map1.get(map2.get("sl")))?String.valueOf(map1.get(map2.get("sl"))):null);
                        info.add(ObjectUtils.isNotEmpty(map1.get(map2.get("kpje")))?String.valueOf(map1.get(map2.get("kpje"))):null);
                        info.add(ObjectUtils.isNotEmpty(map1.get(map2.get("bqzfje")))?String.valueOf(map1.get(map2.get("bqzfje"))):null);
                        if (ObjectUtils.isNotEmpty(map1.get(map2.get("kpje")))) {
                            BigDecimal de = new BigDecimal((String)map1.get(map2.get("kpje")));
                            ljkpje = ljkpje.add(de);
                        }
                    }
                    // 历次累计开票金额合计 / 价税合计 = 占比
                    BigDecimal ratio = BigDecimal.ZERO;
                    if (ObjectUtils.isNotEmpty(map1.get("initZongjiaSum"))) {
                        BigDecimal de = (BigDecimal) map1.get("initZongjiaSum");
                        if (de.compareTo(BigDecimal.ZERO) > 0) {
                            ratio = ljkpje.divide(de, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        }
                    }
                    info.add(ratio.toString() + "%");
                    info.add(ObjectUtils.isNotEmpty(map1.get("ljfkje"))?String.valueOf(map1.get("ljfkje")):null);
                    total.add(info);
                }
            }

            //总计
            if (CollectionUtils.isNotEmpty(mapTotal)){
                List<String> info1 = new ArrayList<>();
                info1.add(null);
                info1.add("总计");
                info1.add(null);
                info1.add(null);
                info1.add(ObjectUtils.isNotEmpty(mapTotal.get("rongliangTotal"))?String.valueOf(mapTotal.get("rongliangTotal")):null);
                info1.add(null);
                info1.add(null);
                info1.add(ObjectUtils.isNotEmpty(mapTotal.get("zongjiaTotal"))?String.valueOf(mapTotal.get("zongjiaTotal")):null);
                info1.add(null);
                for (int i=0;i<resultHeaderList.size();i++){
                    Map<String, Object> map2 = resultHeaderList.get(i);
                    info1.add(null);
                    info1.add(ObjectUtils.isNotEmpty(mapTotal.get(map2.get("kpje")))?String.valueOf(mapTotal.get(map2.get("kpje"))):null);
                    info1.add(ObjectUtils.isNotEmpty(mapTotal.get(map2.get("bqzfje")))?String.valueOf(mapTotal.get(map2.get("bqzfje"))):null);
                }
                info1.add(ObjectUtils.isNotEmpty(mapTotal.get("ljkfje"))?String.valueOf(mapTotal.get("ljkfje")):null);
                total.add(info1);
            }


            int[] cols = {0,1,7}; // 合并列
            int row = 2; // 从第二行开始合并
            int[] intArray = new int[resultHeaderList.size()];//新建一个int类型数组
            for (int i = 0; i <resultHeaderList.size(); i++) {
                intArray[i] = 8+(i+1)*3;
            }
            try {
                String fileName = URLEncoder.encode("开票明细详情", "UTF-8").replaceAll("\\+", "%20");

                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setCharacterEncoding("utf-8");
                response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
                EasyExcel.write(response.getOutputStream())
                    .head(heads)
                    .registerWriteHandler(new ExcelMergeHandler(row, cols))
                    .registerWriteHandler(new ExcelMergeHandlerTotal(row, intArray))
                    .registerWriteHandler(new CustomCellWriteWidthConfig())//自适应列宽引用方式
                    .registerWriteHandler(new HorizontalCellStyleStrategy(ExcelStyleHandler.getHeadStyle(), ExcelStyleHandler.getContentStyle()))
                    .sheet("开票明细详情")
                    .doWrite(total);
            }  catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 查询审批状态
     */
    @SaCheckLogin
    @GetMapping("/getApprovalStatus")
    public R<Map<String, Object>> getApprovalStatus(String bdId,String zdId) {
        return R.ok(null,iCmBaContractSheetsService.getApprovalStatus(bdId,zdId));
    }

    /**
     * 项目信息管理-合同清单验证
     */
    @SaCheckLogin
    @GetMapping("/check")
    public R check(String bdId) {
        return iCmBaContractSheetsService.check(bdId);
    }
}
